package com.coin900.coin.server.coin.ctrl;

import com.coin900.coin.base.AjaxResponse;
import com.coin900.coin.base.FuConstants;
import com.coin900.coin.base.mail.MailSender;
import com.coin900.coin.base.mail.ResetPwdMail;
import com.coin900.coin.base.utils.MailUtils;
import com.coin900.coin.persist.coin.CoinMailVerifyRecordVO;
import com.coin900.coin.persist.fu.FuUserVO;
import com.coin900.coin.server.coin.form.ForgetPasswordForm;
import com.coin900.coin.server.config.ShiroConfig;
import com.coin900.coin.service.coin.ICoinMailVerifyRecordService;
import com.coin900.coin.service.fu.IFuUserService;
import com.value.exception.BusinessException;
import com.value.utils.Md5Encoder;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 用户相关
 *
 * @author
 * @create
 **/
@Controller
public class CoinUserCtrl extends CoinController {

    /**
     * 验证码过期时间 15 min ，5 * 60 = 300
     */
    private static int EXPIRETIME = 300;
    private static final Log logger = LogFactory.getLog(ShiroConfig.class);

    /**
     * 发送激活邮件
     *
     * @param
     * @param request
     * @return
     */
    @RequestMapping(value = "/user/send_activate_mail", method = RequestMethod.GET)
    public ModelAndView create(HttpServletRequest request) {
        FuUserVO user = getUser();
        AjaxResponse response = super.buildAjaxResponse(request);
        if (user.getEmailStatus() == 1) {
            throw new BusinessException("邮件已激活,无需发送邮件");
        }
        if (StringUtils.isEmpty(user.getEmail())) {
            throw new BusinessException("未设置邮箱地址，无法发送激活邮件");
        }
        CoinMailVerifyRecordVO coinMailVerifyRecordVO = new CoinMailVerifyRecordVO();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, 30);
        Date time = calendar.getTime();
        coinMailVerifyRecordVO.setExpiryTime(time);
        coinMailVerifyRecordVO.setUserId(user.getId());
        coinMailVerifyRecordVO.setMailBox(user.getEmail());
        coinMailVerifyRecordVO.setCMInfor(user);
        try {
            mailVerifyRecordService.insertCoinMailVerifyRecord(coinMailVerifyRecordVO);
        } catch (IOException e) {
            throw new BusinessException("激活邮件发送失败");
        }
        return response.getMav();
    }

    /**
     * 激活邮箱
     *
     * @param
     * @param request
     * @return
     */
    @RequestMapping(value = "/coin/activate_mail", method = RequestMethod.GET)
    public Object activate_mail(@RequestParam String verifyToken, HttpServletRequest request) {
        AjaxResponse response = super.buildAjaxResponse(request);
        Map<String, Object> params = new HashMap<>();
        params.put("verifyToken", verifyToken);
        params.put("verifyTime", true);
        List<CoinMailVerifyRecordVO> coinMailVerifyRecordVOS = mailVerifyRecordService.loadCoinMailVerifyRecord(params);
        if (coinMailVerifyRecordVOS.isEmpty()) {
            logger.error("verifyToken-timeOut:"+verifyToken);
            //跳到首页
            return new RedirectView("/index?viewType=page", false);
        }

        CoinMailVerifyRecordVO coinMailVerifyRecordVO = coinMailVerifyRecordVOS.get(0);
        Long userId = coinMailVerifyRecordVO.getUserId();

        params.put("id", userId);
        List<FuUserVO> fuUserVOS = userService.loadFuUser(params);
        FuUserVO fuUserVO = fuUserVOS.get(0);
        //判断当前邮箱 和发送激活邮箱是否一致
        if (!fuUserVO.getEmail().equals(coinMailVerifyRecordVO.getMailBox())) {
            logger.error("当前邮箱不一致"+fuUserVO.getEmail()+"---"+coinMailVerifyRecordVO.getMailBox());
            return new RedirectView("/index?viewType=page", false);
        }

        fuUserVO.setEmailStatus(1);
        fuUserVO.setModifiedDate(new Date());
        userService.updateFuUser(fuUserVO);
        FuUserVO user = getUser();
        if (user == null || user.getId().equals(userId)) {
            //更新session内用户信息
            super.setUser(fuUserVO);
            Subject currentUser = SecurityUtils.getSubject();
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(fuUserVO.getUsername(), fuUserVO.getPassword());
            usernamePasswordToken.setRememberMe(true);
            currentUser.login(usernamePasswordToken);
            Session session = currentUser.getSession();
            session.setAttribute("user", fuUserVO);
        }
        //跳到首页
        return new RedirectView("/index?viewType=page", false);
    }

    /**
     * 跳发送忘记密码邮件的界面
     * <p>
     * *@param viewType
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/forget-pwd", method = RequestMethod.GET)
    public ModelAndView forgetEmailPage(@RequestParam(required = false) String viewType,
                                        HttpServletRequest request) {
        ModelAndView modelAndView = super.buildView(request, "user/forget-email");
        return modelAndView;
    }


    /**
     * 忘记密码，发送修改邮件
     * 只有 TokenOK 的用户才能修改密码
     *
     * @param email
     * @param request
     * @return
     */
    @RequestMapping(value = "/send-forget-password", method = RequestMethod.GET)
    public ModelAndView sendForgetwordEmial(@RequestParam String email,
                                            HttpServletRequest request) {
        Map<String, Object> params = new HashMap<>();
        params.put("username", email);
        params.put("userType", FuConstants.FU_USER_TYPE_TOKENOK);
        params.put("dataStatus", 1);
        params.put("userStatus", 1);
        List<FuUserVO> fuUserVOS = this.userService.loadFuUser(params);
        if (fuUserVOS.isEmpty()) {
            throw new BusinessException("用户不存在或者未激活");
        }

        // email - token 键值对，5 min 失效，存入 redis
        String token = MailUtils.buildMailVerifyToken();
        this.redisTemplate.opsForValue().set(token, email);
        this.redisTemplate.expire(token, EXPIRETIME, TimeUnit.SECONDS);
        // 发送邮件
        ResetPwdMail resetPwdMail = new ResetPwdMail();
        resetPwdMail.setClickUrl("http://www.fu.coin/pwd-modify?token=" + token);
        resetPwdMail.setToEMail(email);
        resetPwdMail.setSubject("忘记密码");
        MailSender.sendMail(resetPwdMail);
        AjaxResponse response = super.buildAjaxResponse(request);
        return response.getMav();
    }

    /**
     * 跳转到修改密码的界面
     *
     * @param token
     * @param request
     * @return
     */
    @RequestMapping(value = "/pwd-modify", method = RequestMethod.GET)
    public ModelAndView modifyPasswordPage(@RequestParam String token,
                                           HttpServletRequest request) {
        ModelAndView modelAndView = super.buildView(request, "user/forget-modify");
        modelAndView.addObject("token", token);
        return modelAndView;
    }

    /**
     * 忘记密码，修改密码
     *
     * @param forgetPasswordForm
     * @param request
     * @return
     */
    @RequestMapping(value = "/forget-password", method = RequestMethod.PATCH)
    public Object modifyPassword(@RequestBody ForgetPasswordForm forgetPasswordForm,
                                 HttpServletRequest request) {

        String token = forgetPasswordForm.getToken();
        String password = forgetPasswordForm.getPassword();
        String repassword = forgetPasswordForm.getRepassword();
        if (!redisTemplate.hasKey(token)) {
            throw new BusinessException("超出修改时间");
        } else {
            String email = (String) this.redisTemplate.opsForValue().get(token);
            if (password.equals(repassword)) {
                // 修改密码
                Map<String, Object> params = new HashMap<>();
                params.put("username", email);
                params.put("userType", FuConstants.FU_USER_TYPE_TOKENOK);
                params.put("dataStatus", 1);
                params.put("userStatus", 1);
                List<FuUserVO> fuUserVOS = this.userService.loadFuUser(params);
                if (fuUserVOS.isEmpty()) {
                    throw new BusinessException("用户不存在或者未激活");
                }
                FuUserVO userVO = fuUserVOS.get(0);
                userVO.setPassword(Md5Encoder.generateCode(password));
                this.userService.updateFuUser(userVO);
                // 修改成功销毁记录
                this.redisTemplate.delete(token);
            } else {
                throw new BusinessException("两次密码不一样");
            }
        }
        AjaxResponse response = super.buildAjaxResponse(request);
        return response.getMav();
    }

    @Autowired
    private ICoinMailVerifyRecordService mailVerifyRecordService;
    @Autowired
    private IFuUserService userService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
}
